package com.jnshu.service.impl;

import com.jnshu.dao.SignMapper;
import com.jnshu.dao.UserMapper;
import com.jnshu.dao.UserTaskRelationMapper;
import com.jnshu.dto.sign.BackSignDto;
import com.jnshu.dto.sign.UserSignDto;
import com.jnshu.exception.MyException;
import com.jnshu.pojo.Sign;
import com.jnshu.pojo.User;
import com.jnshu.pojo.UserTaskRelation;
import com.jnshu.service.SignService;
import com.jnshu.tools.TimeUtil;
import com.jnshu.tools.resultUtils.RUtil;
import com.jnshu.tools.resultUtils.ResultBean;
import com.jnshu.tools.resultUtils.ResultEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import java.util.List;

/**
 * @author Martin
 * @date 2019/8/8 10:15
 * 签到接口实现类
 */
@Slf4j
@Service
public class SignServiceImpl implements SignService {
    @Resource
    UserMapper userMapper;
    @Resource
    SignMapper signMapper;
    @Resource
    UserTaskRelationMapper userTaskRelationMapper;

    /**
     * 返回签到页详情
     * @param id
     * @return userSignDto
     */
    @Override
    public ResultBean backBySign(Long id) {
        log.info("签到页查询用户的id为："+id);
        //获取该用户的数据信息
        User user = userMapper.selectByPrimaryKey(id);
        //查询数据库签到表中是否有该用户的签到记录
        Sign sign = signMapper.selectByUserId(id);
        //用于存放返回给前端数据的对象
        UserSignDto userSignDto = new UserSignDto();
        //判断用户数据是否存在
        if (user == null){
            throw new MyException(501,"请求用户或资源不存在");
        }
        //将userSignDto中与user相同的属性赋值给user
        BeanUtils.copyProperties(user,userSignDto);
        if (sign == null){
            log.info("用户无签到记录");
            userSignDto.setSignStatus(0);
            //返回查询到的用户签到数据
            return RUtil.ok(userSignDto);
        }
        //将userSignDto中与sign相同的属性赋值给sign
        BeanUtils.copyProperties(sign,userSignDto);
        //获取上次签到时间
        long prevSign = userSignDto.getPrev();
        //上一次的签到时间和现在的时间比较是否为同一天,结果作为签到状态
        userSignDto.setSignStatus(TimeUtil.isSameDayOfMillis(prevSign,System.currentTimeMillis()));
        //前端根据userSignDto.signStatus的值判断用户是否已经签过到了
        return RUtil.ok(userSignDto);
    }

    /**
     * 用户签到，更新签到表和用户表
     * @param id
     * @return
     */
    @Override
    @Transactional
    public ResultBean updateByUser(Long id) {
        log.info("签到用户Id为："+id);
        //用于返回签到后的信息的数据对象
        BackSignDto backSignDto = new BackSignDto();
        //设置数据对象为用户id
        backSignDto.setId(id);
        //查询数据库签到表中是否有该用户的签到记录
        Sign sign = signMapper.selectByUserId(id);
        //获取该用户的数据信息
        User user = userMapper.selectByPrimaryKey(id);
        //获取该用户的每日任务的数据
        List<UserTaskRelation> userTaskList = userTaskRelationMapper.selectByUserId(id);
        //判断是否有签到数据
        if (sign == null){
            log.info("签到表没有该用户的签到记录，为第一次签到");
            Sign newSign = new Sign();
            //创建一条签到记录
            newSign.setUserId(id);
            //连续签到+1
            newSign.setContinuous(1);
            //设置签到记录的签到时间
            newSign.setCreateAt(System.currentTimeMillis());
            //设置签到记录创建人id
            newSign.setCreateBy(id);
            //设置第一次签到的prev
            newSign.setPrev(newSign.getCreateAt());
            //同时更新用户积分
            user.setIntegral(1);
            //将数据更新到数据表中
            if (createTransaction(newSign,user)){
                return RUtil.error(ResultEnum.FAILURE);
            }
            log.info("签到表插入一条信息为："+newSign);
            //将签到后sign表中的数据copy给BackUserDto
            BeanUtils.copyProperties(newSign,backSignDto);
            //将签到后user表中的数据copy给BackUserDto
            BeanUtils.copyProperties(user,backSignDto);
            //两个表都没有的字段
            backSignDto.setAddIntegral(1);
            backSignDto.setSignStatus(1);
            log.info("userSignDto中的数据为："+backSignDto);
            //返回给前端的请求状态及数据
            return RUtil.ok(backSignDto);
        }
        log.info("签到表中有该用户的签到记录");
        //获取用户上次签到时间
        long prevSign = sign.getPrev();
        //判断上次签到和本次签到是否连续
        if (!TimeUtil.isContinuous(prevSign)){
            log.info("用户两次签到为非连续签到");
            //将连续签到天数重置为1
            sign.setContinuous(1);
            //替换上一次签到时间
            sign.setPrev(System.currentTimeMillis());
            //修改表格更新时间
            sign.setUpdateAt(System.currentTimeMillis());
            //修改人id
            sign.setUpdateBy(id);
            log.info("更新签到表中信息："+sign);
            user.setIntegral(user.getIntegral()+1);
            log.info("更新用户表中的积分总数："+user);
            //用户表更新时间
            user.setUpdateAt(System.currentTimeMillis());
            //将更新后对象数据写入数据库
            if (updateTransaction(sign,user)){
                return RUtil.error(ResultEnum.FAILURE);
            }
            //将签到后sign表中的数据copy给BackUserDto
            BeanUtils.copyProperties(sign,backSignDto);
            //将签到后user表中的数据copy给BackUserDto
            BeanUtils.copyProperties(user,backSignDto);
            backSignDto.setSignStatus(1);
            backSignDto.setAddIntegral(1);
            //返回给前端的请求状态及数据
            return RUtil.ok(backSignDto);
        }//连续签到次数+1后再进行是否大于4的判断
        else if (sign.getContinuous()+1 <=4){
            log.info("用户连续签到小于等于4时");
            //用户连续签到新增积分
            user.setIntegral(user.getIntegral()+3);
            //返回给前端的数据
            backSignDto.setAddIntegral(3);
            //用户连续签到状态变更
            sign.setContinuous(sign.getContinuous()+1);
        }//连续签到次数+1后大于4判断
        else if (4 < (sign.getContinuous()+1) && (sign.getContinuous()+1) < 7){
            log.info("用户签到次数大于4小于7时");
            //用户连续签到新增积分
            user.setIntegral(user.getIntegral()+5);
            //返回给前端的数据
            backSignDto.setAddIntegral(5);
            //用户连续签到状态变更
            sign.setContinuous(sign.getContinuous()+1);
        }else if (sign.getContinuous()+1 > 6){
            log.info("用户连续签到次数大于等于7");
            //用户连续牵动新增积分
            user.setIntegral(user.getIntegral()+7);
            //返给前端的数据
            backSignDto.setAddIntegral(7);
            //用户连续签到状态变更
            sign.setContinuous(sign.getContinuous()+1);
        }
            //将本次签到时间替换上一次签到时间
            sign.setPrev(System.currentTimeMillis());
            //签到表更新时间
            sign.setUpdateAt(System.currentTimeMillis());
            //签到表修改人
            sign.setUpdateBy(id);
            //用户表更新时间
            user.setUpdateAt(System.currentTimeMillis());
        if (updateTransaction(sign,user)){
            return RUtil.error(ResultEnum.FAILURE);
        }
            //将签到信息传给前端
            BeanUtils.copyProperties(sign,backSignDto);
            BeanUtils.copyProperties(user,backSignDto);
            backSignDto.setSignStatus(1);
        return RUtil.ok(backSignDto);
    }

    //事务性更新数据表
    private boolean updateTransaction(Sign sign,User user){
        try {
            log.info("开始更新签到事务判断处理========================================");
            userMapper.updateByPrimaryKeySelective(user);
            signMapper.updateByIdSelective(sign);
        }catch (Exception e){
            log.info("更新表格失败，手动进行回滚");
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return true;
        }
        //数据表格更新成功
        return false;
    }

    //事务性创建数据表
    private boolean createTransaction(Sign sign,User user){
        try {
            log.info("开始创建签到事务判断处理========================================");
            userMapper.updateByPrimaryKeySelective(user);
            signMapper.insertSelective(sign);
        }catch (Exception e){
            log.info("创建表格失败，手动进行回滚");
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return true;
        }
        //数据创建成功
        return false;
    }

}
